#include "user_global.h"
#include "modbus.h"
#include "user_device.h"
#include "crc.h"
#include <string.h>
//#include "device_memory.h"
#include "stdlib.h"


#define MAX_READ_BIT                984 // 最大读取的RO/RW-bit数量
#define MAX_WRITE_BIT               952 // 最大写入的RW-bit数量
#define MAX_READ_WORD               61  // 最大读取的RO/RW-WORD数量
#define MAX_WRITE_WORD              59  // 最大写入的RW-WORD数量


//将多字节数转换为小端模式
ushort from_little_endian_16(ushort n)
{
    return (n << 8) | (n >> 8);
}

//将多字节数转换为小端模式
ulong from_little_endian_32(ulong n)
{
    return  ((n << 24) & 0xFF000000) |
            ((n << 8 ) & 0x00FF0000) |
            ((n >> 8 ) & 0x0000FF00) |
            ((n >> 24) & 0x000000FF);
}


// 读文件请求
typedef struct FILE_REQUEST
{
    uchar fid;        // 文件号
    uchar len;        // 读取长度
    ushort addr;    // 记录地址
} FILE_REQUEST;


void No_Response(void)
{
    ++server_no_response_count;
}

void Response(void)
{
    uchar event;

    // 广播消息不应答
    if (!uart0_buf[0])
    {
        No_Response();
        return;
    }

    event = EVENT_SENT | (ps_listen_only ? EVENT_LISTEN_ONLY : 0);
    if (!Uart0_Send_Message())
        event |= EVENT_WRITE_TIMEOUT;

    Log_Event(event);
}

void Exception_Response(uchar err)
{
    uchar event;

    // 广播消息不应答
    if (!uart0_buf[0])
    {
        No_Response();
        return;
    }

    uart0_buf[1] |= 0x80;
    uart0_buf[2] = err;
    uart0_len = 3;

    event = EVENT_SENT | (ps_listen_only ? EVENT_LISTEN_ONLY : 0);
    switch(err)
    {
    case ILLEGAL_FUNCTION:
    case ILLEGAL_DATA_ADDRESS:
    case ILLEGAL_DATA_VALUE:
        event |= EVENT_READ_EXCEPTION;
        break;
    case SERVER_DEVICE_FAILURE:
        event |= EVENT_ABORT_EXCEPTION;
        break;
    case ACKNOWLEDGE:
    case SERVER_DEVICE_BUSY:
        event |= EVENT_BUSY_EXCEPTION;
        break;
    default:
        event |= EVENT_EXCEPTION;
        break;
    }

    if (!Uart0_Send_Message())
        event |= EVENT_WRITE_TIMEOUT;

    ++server_exception_count;
    Log_Event(event);
}

// 处理上位机请求
// 数据帧: [地址] [指令] [数据...] [CRC..2byte]
void Process_Request(void)
{
    uchar addr = uart0_buf[0];
    uchar cmd = uart0_buf[1];
    uchar dataLen = uart0_len - 4;
    uchar n;
    ushort index;
    ushort count;

    ++bus_message_count;

    // 超过了最大长度
    if (uart0_len > UART0_BUF_SIZE)
    {
        //++bus_char_overrun_count;
        ++bus_error_count;
        return;
    }

    // 检查数据长度和CRC
    if (uart0_len < 4 || !check_message_crc(uart0_buf, uart0_len))
    {
        ++bus_error_count;
        return;
    }

    // addr = 0: 广播地址
    if (addr != server_address)
    {
        if(uart0_buf[1] & 0x80)
            ++bus_exception_count;
        return;
    }


    ++server_message_count;

    // 记录接收事件
    Log_Event(EVENT_RECEIVED
              | (addr ? 0 : EVENT_BROADCAST)
              | (ps_listen_only ? EVENT_LISTEN_ONLY : 0));

    // 只听模式, 只有重启指令执行
    if (ps_listen_only && (cmd != 0x08 || *(short*)&uart0_buf[2] != 0x01))
    {
        No_Response();
        return;
    }

    switch(cmd)
    {
    case 0x01:      // 读RW-bit
        index = from_little_endian_16(*(ushort *)&uart0_buf[2]);
        count = from_little_endian_16(*(ushort *)&uart0_buf[4]);

        if (dataLen != 4 || count < 1 || count > MAX_READ_BIT)
            Exception_Response(ILLEGAL_DATA_VALUE);
        else if (index >= RW_BIT_COUNT || index + count > RW_BIT_COUNT)
            Exception_Response(ILLEGAL_DATA_ADDRESS);
        else
        {
            uart0_len = 2;
            uart0_buf[uart0_len++] = (count+7) >> 3;
            //uart0_buf[uart0_len++] = (uchar)count;
            while(count)
            {
                n = count > 8 ? 8 : count;
                uart0_buf[uart0_len++] = Read_RW_bit(index, n);
                index += n;
                count -= n;
            }

            Response();
        }
        break;

    case 0x02:      // 读RO-bit
        index = from_little_endian_16(*(ushort *)&uart0_buf[2]);
        count = from_little_endian_16(*(ushort *)&uart0_buf[4]);

        if (dataLen != 4 || count < 1 || count > MAX_READ_BIT)
            Exception_Response(ILLEGAL_DATA_VALUE);
        else if (index >= RO_BIT_COUNT || index + count > RO_BIT_COUNT)
            Exception_Response(ILLEGAL_DATA_ADDRESS);
        else
        {
            uart0_len = 2;
            uart0_buf[uart0_len++] = (count+7) >> 3;
            //uart0_buf[uart0_len++] = (uchar)count;
            while(count)
            {
                n = count > 8 ? 8 : count;
                uart0_buf[uart0_len++] = Read_RO_bit(index, n);
                index += n;
                count -= n;
            }

            Response();
        }
        break;

    case 0x03:      // 读RW-word
        index = from_little_endian_16(*(ushort *)&uart0_buf[2]);
        count = from_little_endian_16(*(ushort *)&uart0_buf[4]);

        if (dataLen != 4 || count < 1 || count > MAX_READ_WORD)
            Exception_Response(ILLEGAL_DATA_VALUE);
        else if (index >= RW_WORD_COUNT || index + count > RW_WORD_COUNT)
            Exception_Response(ILLEGAL_DATA_ADDRESS);
        else
        {
            uart0_len = 2;
            uart0_buf[uart0_len++] = count << 1;
            while(count--)
            {
                *(ushort*)&uart0_buf[uart0_len] = from_little_endian_16(Read_RW_word(index++));
                uart0_len += 2;
            }

            Response();
        }
        break;

    case 0x04:      // 读RO-word
        index = from_little_endian_16(*(ushort *)&uart0_buf[2]);
        count = from_little_endian_16(*(ushort *)&uart0_buf[4]);

        if (dataLen != 4 || count < 1 || count > MAX_READ_WORD)
            Exception_Response(ILLEGAL_DATA_VALUE);
        else if (index >= RO_WORD_COUNT || index + count > RO_WORD_COUNT)
            Exception_Response(ILLEGAL_DATA_ADDRESS);
        else
        {
            uart0_len = 2;
            uart0_buf[uart0_len++] = count << 1;
            while(count--)
            {
                *(ushort*)&uart0_buf[uart0_len] = from_little_endian_16(Read_RO_word(index++));
                uart0_len += 2;
            }

            Response();
        }
        break;

    case 0x05:      // 写单个RW-bit
        index = from_little_endian_16(*(ushort *)&uart0_buf[2]);
        count = from_little_endian_16(*(ushort *)&uart0_buf[4]);

        if (dataLen != 4 || (count != 0x0000 && count != 0xFF00))
            Exception_Response(ILLEGAL_DATA_VALUE);
        else if (index >= RW_WORD_COUNT)
            Exception_Response(ILLEGAL_DATA_ADDRESS);
        else
        {
            Write_bit(index, count >> 8, 1);
            //Write_bit(index, count);
            uart0_len = 6;
            Response();
        }
        break;

    case 0x06:      // 写单个RW-word
        index = from_little_endian_16(*(ushort *)&uart0_buf[2]);
        count = from_little_endian_16(*(ushort *)&uart0_buf[4]);

        if (dataLen != 4)
            Exception_Response(ILLEGAL_DATA_VALUE);
        else if (index >= RW_WORD_COUNT)
            Exception_Response(ILLEGAL_DATA_ADDRESS);
        else
        {
            Write_word(index, count);
            uart0_len = 6;
            Response();
        }
        break;

    case 0x07:      // 读取异常状态
        uart0_buf[2] = Read_Exception();
        uart0_len = 3;
        Response();
        break;

    case 0x08:      // 诊断
        if (dataLen < 2)
            Exception_Response(ILLEGAL_DATA_VALUE);
        else
            Diagnose();
        break;

    case 0x0B:      // 读取事件计数
        n = event_count > MAX_EVENT_COUNT ? MAX_EVENT_COUNT : event_count;
        *(ushort *)&uart0_buf[2] = from_little_endian_16(ps_server_busy ? 0xFFFF : ro_word.server_status);
        *(ushort *)&uart0_buf[4] = from_little_endian_16(n);
        uart0_len = 6;
        Response();
        break;

    case 0x0C:      // 读取事件记录
        n = event_count > MAX_EVENT_COUNT ? MAX_EVENT_COUNT : event_count;
        uart0_len = 2;
        uart0_buf[uart0_len++] = n + 6;
        *(ushort*)&uart0_buf[uart0_len] = from_little_endian_16(ps_server_busy ? 0xFFFF : ro_word.server_status);
        uart0_len += 2;
        *(ushort*)&uart0_buf[uart0_len] = from_little_endian_16(n);
        uart0_len += 2;
        *(ushort*)&uart0_buf[uart0_len] =from_little_endian_16(bus_message_count);
        uart0_len += 2;
        for(addr=event_count; n--; --addr)
            uart0_buf[uart0_len++] = event_log[addr & MAX_EVENT_MASK];
        Response();
        break;

    case 0x0F:      // 写多个RW-bit
        index = from_little_endian_16(*(ushort *)&uart0_buf[2]);
        count = from_little_endian_16(*(ushort *)&uart0_buf[4]);

        if (dataLen != uart0_buf[6] + 5 || count < 1 || count > MAX_WRITE_BIT)
            Exception_Response(ILLEGAL_DATA_VALUE);
        else if (index >= RW_BIT_COUNT || index + count > RW_BIT_COUNT)
            Exception_Response(ILLEGAL_DATA_ADDRESS);
        else
        {
            addr = 7;
            while(count)
            {
                n = count > 8 ? 8 : count;
                Write_bit(index, uart0_buf[addr++], n);
                count -= n;
                index += n;
            }
            uart0_len = 6;
            Response();
        }
        break;

    case 0x10:      // 写多个RW-word
        index = from_little_endian_16(*(ushort *)&uart0_buf[2]);
        count = from_little_endian_16(*(ushort *)&uart0_buf[4]);

        if (dataLen != uart0_buf[6] + 5 || count < 1 || count > MAX_WRITE_WORD)
            Exception_Response(ILLEGAL_DATA_VALUE);
        else if (index >= RW_WORD_COUNT || index + count > RW_WORD_COUNT)
            Exception_Response(ILLEGAL_DATA_ADDRESS);
        else
        {
            n = 7;
            while(count--)
            {
                Write_word(index++, from_little_endian_16(*(ushort*)&uart0_buf[n]));
                n += 2;
            }
            uart0_len = 6;
            Response();
        }
        break;

#if FILE_COUNT
    case 0x14:      // 读文件记录
        addr = uart0_buf[2] / 7;    // 子请求数
        if (dataLen != uart0_buf[2] + 1 || addr > MAX_FILE_REQUEST)
            Exception_Response(ILLEGAL_DATA_VALUE);
        else
        {
            FILE_REQUEST req[MAX_FILE_REQUEST];
            uchar *p = uart0_buf + 3;
            cmd = 0;    // 返回的数据长度

            // 计算请求返回的长度
            for(n = 0; n < addr; ++n, p += 7)
            {
                req[n].fid  = from_little_endian_16(*(ushort*)&p[1]) - 1;    // 请求文件号=>索引
                req[n].addr = from_little_endian_16(*(ushort*)&p[3]);        // 请求地址
                req[n].len  = from_little_endian_16(*(ushort*)&p[5]);        // 请求记录数

                // 检查文件类型和文件号正确性
                if (p[0] != 6 || req[n].fid >= FILE_COUNT)
                {
                    Exception_Response(ILLEGAL_DATA_VALUE);
                    return;
                }

                // 从请求地址处能读取的最大记录数
                count = File_Size(req[n].fid);
                if (req[n].addr >= count)
                    req[n].len = 0;
                else
                {
                    count = count - req[n].addr;
                    if (req[n].len > count)
                        req[n].len = count;
                }

                // 返回数据的长度: 记录数x2 + 应答长度 + 应答类型
                cmd += (req[n].len << 1) + 2;

                // 请求的数据长度超过消息允许的长度
                if (cmd > UART0_BUF_SIZE - 5)
                {
                    Exception_Response(ILLEGAL_DATA_VALUE);
                    return;
                }
            }

            // 开始读取文件请求
            p = &uart0_buf[2];    // 读文件数据
            *p++ = cmd;            // 字节数

            // 所有子请求
            for(n = 0; n < addr; ++n)
            {
                *p++ = (req[n].len << 1) + 1;    // 子请求应答长度
                *p++ = 6;                        // 子请求类型, 必须为6
                while(req[n].len--)
                {
                    *(ushort*)p = from_little_endian_16(Read_File(req[n].fid, req[n].addr++));
                    p += 2;
                }
            }

            uart0_len = p - uart0_buf;
            Response();
        }
        break;

    case 0x15:      // 写文件记录
        if (dataLen != uart0_buf[2] + 1)
            Exception_Response(ILLEGAL_DATA_VALUE);
        else
        {
            // 检验数据正确性
            for (n = 0; n < uart0_buf[2]; )
            {
                if (uart0_buf[n+3] != 6     // 请求类型
                        || from_little_endian_16(*(ushort*)&uart0_buf[n+3+1]) - 1 >= FILE_COUNT     // 文件号
                        //|| *(ushort*)&uart0_buf[n+3+3] >=         // 记录号, 根据需要检查
                        )
                {
                    Exception_Response(ILLEGAL_DATA_VALUE);
                    return;
                }

                n += 7 + (from_little_endian_16(*(ushort*)&uart0_buf[n+3+5]) << 1);
            }

            // 写入记录
            for (n = 0; n < uart0_buf[2]; )
            {
                addr  = from_little_endian_16(*(ushort*)&uart0_buf[n+3+1]) - 1;    // 文件索引号
                index = from_little_endian_16(*(ushort*)&uart0_buf[n+3+3]);        // 记录号
                count = from_little_endian_16(*(ushort*)&uart0_buf[n+3+5]);        // 记录长度
                n += 7;

                for(; count--; n += 2)
                    Write_File(addr, index++, from_little_endian_16(*(ushort*)&uart0_buf[n+3]));
            }

            // 原样返回
            uart0_len -= 2;
            Response();
        }
        break;
#endif


    case 0x16:      // 掩码写RW-word
        index = from_little_endian_16(*(ushort*)&uart0_buf[2]);
        if (dataLen != 6)
            Exception_Response(ILLEGAL_DATA_VALUE);
        else if (index >= RW_WORD_COUNT)
            Exception_Response(ILLEGAL_DATA_ADDRESS);
        else
        {
            count = from_little_endian_16(Read_RW_word(index));
            count &= from_little_endian_16(*(ushort*)&uart0_buf[4]);
            count |= from_little_endian_16(~*(ushort*)&uart0_buf[4]) & from_little_endian_16(*(ushort*)&uart0_buf[6]);
            Write_word(index, count);
            uart0_len -= 2;
            Response();
        }
        break;

    case 0x17:      // 读/写多个RW-word
        // 检验读操作正确性
        index = from_little_endian_16(*(ushort *)&uart0_buf[2]);
        count = from_little_endian_16(*(ushort *)&uart0_buf[4]);

        if (count < 1 || count > MAX_READ_WORD)
            Exception_Response(ILLEGAL_DATA_VALUE);
        else if (index >= RW_WORD_COUNT || index + count > RW_WORD_COUNT)
            Exception_Response(ILLEGAL_DATA_ADDRESS);

        // 检验写操作正确性
        index = from_little_endian_16(*(ushort *)&uart0_buf[6]);
        count = from_little_endian_16(*(ushort *)&uart0_buf[8]);

        if (dataLen != uart0_buf[10] + 9 || count < 1 || count > MAX_WRITE_WORD - 2)
            Exception_Response(ILLEGAL_DATA_VALUE);
        else if (index >= RW_WORD_COUNT || index + count > RW_WORD_COUNT)
            Exception_Response(ILLEGAL_DATA_ADDRESS);

        // 写寄存器
        for(n = 11; count--; n += 2)
            Write_word(index++, from_little_endian_16(*(ushort*)&uart0_buf[n]));

        // 读寄存器
        index = from_little_endian_16(*(ushort *)&uart0_buf[2]);
        count = from_little_endian_16(*(ushort *)&uart0_buf[4]);

        // 字节数
        uart0_len = 2;
        uart0_buf[uart0_len++] = count << 1;

        for(; count--; uart0_len += 2)
            *(ushort*)&uart0_buf[uart0_len] = from_little_endian_16(Read_RW_word(index++));

        Response();
        break;

    case 0x2B:      // 传输接口封装
        if (uart0_buf[2] == 0x0E)   // 读取设备标识
        {
            Read_Identification();
        }
#ifdef _USES_UART1
        else if (uart0_buf[2] == 0x0C)
            Modbus_Gateway();
        else if (uart0_buf[2] == 0x0D)
            Modbus_Transparent();
#endif
        else
            Exception_Response(ILLEGAL_DATA_VALUE);
        break;
        //    case 0x43:        // 读取未读取的EEPROM
        //        index = from_little_endian_16(*(ushort *)&uart0_buf[2]);
        //        count = from_little_endian_16(*(ushort *)&uart0_buf[4]); //count为数据长度

        //        if (dataLen != 4 || count < 1 || count > MEM_BUF_SIZE)
        //            Exception_Response(ILLEGAL_DATA_VALUE);
        //        else if (index >= MAX_MEM_BUF_SIZE || index + count > MAX_MEM_BUF_SIZE)
        //            Exception_Response(ILLEGAL_DATA_ADDRESS);
        //        else if (count != MEM_BUF_SIZE)
        //            Exception_Response(ILLEGAL_DATA_COUNT);
        //        else
        //        {
        //            uart0_len = 2;
        //            uart0_buf[uart0_len++] = count; //返回数据长度
        //
        //            //memcpy(&uart0_buf[uart0_len], &mem_buf[mem_sendRead++ % MEM_BUF_MAX_NUM].buf[0], MEM_BUF_SIZE);
        //            //mem_buf[mem_sendRead % MEM_BUF_MAX_NUM].buf[3]++;
        ////            if(mem_read_add_ptr != mem_write_add_ptr)
        ////            {
        ////                TGT_Read_Flash(&uart0_buf[uart0_len],mem_read_add_ptr);
        ////                mem_read_add_ptr += MEM_BUF_SIZE;


        ////                if(mem_read_add_ptr >= MAX_AD_MEM_BUF_SIZE)
        ////                {
        ////                    mem_read_add_ptr = 0;
        ////
        ////                }
        ////                //存储读地址指针
        ////                TGT_Write_Flash((uchar *)mem_read_add_ptr, MEM_READ_PTR_ADD_LOW, 2);
        ////            }
        ////            else{

        ////                Exception_Response(MEMORY_PARITY_ERROR);
        ////            }
        //            uart0_len += count;

        //            Response();
        //        }
        //        break;
        //    case 0x41:        // 读取未读取的EEPROM
        //        index = from_little_endian_16(*(ushort *)&uart0_buf[2]);
        //        count = from_little_endian_16(*(ushort *)&uart0_buf[4]); //count为数据长度

        //        if (dataLen != 4 || count < 1 || count > MEM_BUF_SIZE)
        //            Exception_Response(ILLEGAL_DATA_VALUE);
        //        else if (index >= MAX_MEM_BUF_SIZE || index + count > MAX_MEM_BUF_SIZE)
        //            Exception_Response(ILLEGAL_DATA_ADDRESS);
        //        else if (count != MEM_BUF_SIZE)
        //            Exception_Response(ILLEGAL_DATA_COUNT);
        //        else
        //        {
        //            uart0_len = 2;
        //            uart0_buf[uart0_len++] = count + 4; //返回数据长度
        //            *(ushort *)&uart0_buf[uart0_len] = from_little_endian_16(index); //返回数据长度
        //            uart0_len +=2;
        //            *(ushort *)&uart0_buf[uart0_len] =  from_little_endian_16(MEM_BUF_SIZE); //返回数据长度
        //            uart0_len +=2;
        //            //memcpy(&uart0_buf[uart0_len], &mem_buf[mem_sendRead++ % MEM_BUF_MAX_NUM].buf[0], MEM_BUF_SIZE);
        //            //mem_buf[mem_sendRead % MEM_BUF_MAX_NUM].buf[3]++;

        //            if(TGT_Read_Flash(&uart0_buf[uart0_len],index))
        //            {

        //            }
        //            else{

        //                Exception_Response(MEMORY_PARITY_ERROR);
        //            }
        //            uart0_len += count;

        //            Response();
        //        }
        //        break;


    default:        // 不支持的指令代码
        Exception_Response(ILLEGAL_FUNCTION);
        break;
    }

}


/*
#ifdef _USES_UART1

////////////////////////////////////////////////////////////////////////////////
// UART1

#define NO_READ_RWBIT
//#define NO_READ_RWWORD
//#define NO_WRITE_BIT
//#define NO_READ_FILE

// uart1发送
void Uart1_Send(void)
{
    uart1_rx_pending = 0;
    uart1_tx_pending = 1;
    uart1_rx_len = 0;
    uart1_tx_ptr = uart1_tx_buf;
    uart1_tx_left = uart1_tx_len;

    // 根据协议, 发送前等待4字节时间@115200
    Delay_us(1);
    uart1_tx_pending = 1;
    USART2_Send_Date(uart1_tx_buf,uart1_tx_len);
    uart1_tx_pending = 0;


}

// uart1接收
void Uart1_Read(void)
{
    // 未完成接收
    if (!Uart1_FrameEnded())
        return;

    // 10ms超时
    if (uart1_rx_len == 0)
        uart1_result = UART1_RESULT_TIMEOUT;
    else
    {
        // 接收完成, 检查CRC
        if (uart1_rx_len < 4 || uart1_rx_len > UART1_BUF_SIZE ||
                uart1_rx_buf[0] != uart1_tx_buf[0] ||
                (uart1_rx_buf[1] & 0x7F) != uart1_tx_buf[1] ||
                !check_message_crc(uart1_rx_buf, uart1_rx_len))
        {
            uart1_result = UART1_RESULT_CRC;
        }
        else
        {
            if (uart1_rx_buf[1] & 0x80)
                uart1_result = UART1_RESULT_EXCEPTION;
            else
                uart1_result = UART1_RESULT_OK;
        }
    }

    uart1_rx_pending = 0;
}


#endif  //_USES_UART1*/
